package com.itheima.service.impl;

import com.alibaba.dubbo.config.annotation.Service;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.itheima.constant.MessageConstant;
import com.itheima.entity.PageResult;
import com.itheima.entity.QueryPageBean;
import com.itheima.entity.Result;
import com.itheima.mapper.MemberMapper;
import com.itheima.mapper.OrderMapper;
import com.itheima.mapper.OrdersettingMapper;
import com.itheima.pojo.Member;
import com.itheima.pojo.Order;
import com.itheima.pojo.OrderSetting;
import com.itheima.service.OrderService;
import com.itheima.utils.DateUtils;
import com.itheima.utils.ValidateCodeUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;

@Service(interfaceClass = OrderService.class)
@Transactional
public class OrderServiceImpl implements OrderService {
    @Autowired
    private OrdersettingMapper ordersettingMapper;
    @Autowired
    private MemberMapper memberMapper;
    @Autowired
    private OrderMapper orderMapper;

    /**
     * 体检预约
     *
     * @param map 包含:setmealId,sex,validateCode,telephone,name,idCard,orderDate,orderType
     * @return
     */
    public Result order(Map map) throws Exception {
        //1、检查用户所选择的预约日期是否已经提前进行了预约设置，如果没有设置则无法进行预约
        //1.1获取预约日期
        String orderDate = (String) map.get("orderDate");
        Date date = DateUtils.parseString2Date(orderDate);
        //1.2查询预约设置dao中是否有数据
        OrderSetting orderSetting = ordersettingMapper.findByOrderDate(date);
        if (orderSetting == null) {
            //1.3没有设置,无法预约
            return new Result(false, MessageConstant.SELECTED_DATE_CANNOT_ORDER);
        }

        //2、检查用户所选择的预约日期是否已经约满，如果已经约满则无法预约
        int number = orderSetting.getNumber();//可预约人数
        int reservations = orderSetting.getReservations();//当前预约人数
        if (reservations >= number) {
            //人数已满不能在预约
            return new Result(false, MessageConstant.ORDER_FULL);
        }

        //3、检查用户是否重复预约（同一个用户在同一天预约了同一个套餐），如果是重复预约则无法完成再次预约
        //3.1检查当前用户是否是会员,通过手机号查询
        String telephone = (String) map.get("telephone");//用户输入的手机号
        Member member = memberMapper.findByTelephone(telephone);
        if (member != null) { //是会员
            //3.2获取校验的参数
            Integer memberId = member.getId();//会员id
            String setmealId = (String) map.get("setmealId");//套餐id
            //3.3创建Order对象
            Order order = new Order(memberId, date, Integer.parseInt(setmealId));
            //3.4通过三个条件进行查询是否已经存在数据
            List<Order> orderList = orderMapper.findByCondition(order);
            if (orderList != null && orderList.size() > 0) {
                //已经预约过,不能重复预约
                return new Result(false, MessageConstant.HAS_ORDERED);
            }
        } else { //不是会员
            //4、检查当前用户是否为会员，如果是会员则直接完成预约，如果不是会员则自动完成注册并进行预约
            //4.1不是会员进行会员自动注册
            member = new Member();
            member.setName((String) map.get("name"));
            member.setSex((String) map.get("sex"));
            member.setIdCard((String) map.get("idCard"));
            member.setPhoneNumber(telephone);
            member.setRegTime(new Date());

            //4.2添加数据到会员表
            memberMapper.add(member);
        }

        //5、预约成功，更新当日的已预约人数
        //5.1添加预约信息到数据库
        Order order = new Order(member.getId(), date, (String) map.get("orderType"),
                Order.ORDERSTATUS_NO, Integer.parseInt((String) map.get("setmealId")),
                Integer.parseInt((String) map.get("addressId")), (String) map.get("address"));
        orderMapper.add(order);
        //5.2更新当日已预约人数
        orderSetting.setReservations(orderSetting.getReservations() + 1);
        OrderSetting currentOrderSetting = ordersettingMapper.findByOrderDate(date);
        if (currentOrderSetting.getVersion() != orderSetting.getVersion()) {
            //版本号不等,表示已有其他线程访问,需使用最新的数据进行操作
            currentOrderSetting.setReservations(currentOrderSetting.getReservations() + 1);
            ordersettingMapper.editReservationsByOrderDate(currentOrderSetting);
        } else {
            ordersettingMapper.editReservationsByOrderDate(orderSetting);
        }

        //5.3返回数据,包括预约id
        return new Result(true, MessageConstant.ORDER_SUCCESS, order.getId());
    }

    /**
     * 通过预约id查询对应数据
     *
     * @param orderId
     * @return 获取member体检人, setmeal体检套餐名, orderDate体检日期, orderType预约类型
     */
    public Map findByOrderId(Integer orderId) throws Exception {
        Map map = orderMapper.findById4Detail(orderId);
        //处理map中日期变量
        if (map != null) {
            Date orderDate = (Date) map.get("orderDate");
            String date = DateUtils.parseDate2String(orderDate);
            map.put("orderDate", date);
        }
        return map;
    }

    //查询今日预约数
    public Integer findCountByDate(String currentDateStr) {
        return orderMapper.findCountByDate(currentDateStr);

    }

    //查询今日到诊人数
    public Integer findCountByDateAndVisited(String currentDateString) {
        return orderMapper.findCountByDateAndVisited(currentDateString);
    }

    //查询本周的预约人数
    public Integer findCountByThisWeek(String mondayString, String currentDateString) {
        return orderMapper.findCountByDateScope(mondayString, currentDateString);
    }

    //查询笨猪的到诊人数
    public Integer findCountByThisWeekAndVisited(String mondayString, String currentDateString) {
        return orderMapper.findCountByDateScopeAndVisited(mondayString, currentDateString);
    }

    //查询本月的预约人数
    public Integer findCountByThisMonth(String firstDayOfThisMonthStr, String currentDateString) {
        return orderMapper.findCountByDateScope(firstDayOfThisMonthStr, currentDateString);
    }

    //查询本月的到诊人数
    public Integer findCountByThisMonthAndVisited(String firstDayOfThisMonthStr, String currentDateString) {
        return orderMapper.findCountByDateScopeAndVisited(firstDayOfThisMonthStr, currentDateString);
    }

    /* ======================================================================================================= */

    /**
     * 1.分页+模糊查询查询
     *
     * @param pageBean
     * @return
     */
    @Override
    public PageResult getPage(QueryPageBean pageBean) throws Exception {
        // 分页设置
        PageHelper.startPage(pageBean.getCurrentPage(), pageBean.getPageSize());

        Page<Map> page = orderMapper.getByCondition(pageBean.getQueryString());
        if (page != null && page.getTotal() > 0) {
            for (Map map : page) {
                String orderDate = DateUtils.parseDate2String((Date) map.get("orderDate"));
                map.put("orderDate", orderDate);
            }
        }

        assert page != null;
        return new PageResult(page.getTotal(), page.getResult());
    }

    /**
     * 2.体检预约
     * <p>
     * 第一组参数: map包含:setmealId,sex,validateCode,telephone,name,idCard,orderDate,orderType
     * 第二组参数:
     * ① map包含: name,idCard,orderDate,telephone,sex,orderType
     * ② setMealIds:
     */
    @Override
    public Result create(Integer[] setMealIds, Map map) throws Exception {

        /**1.检查预约设置*/
        Date orderDate = DateUtils.parseString2Date((String) map.get("orderDate"));
        OrderSetting dbOrderSetting = ordersettingMapper.findByOrderDate(orderDate);
        if (dbOrderSetting == null) {
            // 没有体检安排,无法预约,返回结果
            return new Result(false, MessageConstant.SELECTED_DATE_CANNOT_ORDER);
        }

        /**2.检查库存*/
        if (dbOrderSetting.getNumber() <= dbOrderSetting.getReservations())
            // 预约已满,无法预约,返回结果
            return new Result(false, MessageConstant.ORDER_FULL);

        /**3.判断套餐id*/
        boolean flag = true;
        if (setMealIds == null || setMealIds.length == 0) {
            flag = false;
        }

        /**3.检查会员信息:通过联系电话*/
        String telephone = (String) map.get("telephone");
        Member member = memberMapper.findByTelephone(telephone);

        // 前端的套餐id集合
        HashSet<Integer> params = null;
        // 后台收集到的套餐id结合
        HashSet<Integer> dbSetMealIds = null;

        Order order = null;
        String orderType = (String) map.get("orderType");
        Integer addressId = (Integer) map.get("region");

        if (member != null) {
            params = new HashSet<>();
            dbSetMealIds = new HashSet<>();
            // 检查重复预约
            if (flag) {
                for (Integer setMealId : setMealIds) {
                    params.add(setMealId);

                    // 参与查询的数据:会员id,预约日期,套餐id,
                    order = new Order(member.getId(), orderDate, setMealId);
                    List<Order> orders = orderMapper.findByCondition(order);
                    if (orders != null && orders.size() > 0) {
                        for (Order dbOrder : orders) {
                            dbSetMealIds.add(dbOrder.getId());
                        }
                    }
                }
            } else {
                return new Result(false, "客户没有预约体检套餐");
            }

            if (!params.retainAll(dbSetMealIds)) {
                return new Result(false, MessageConstant.HAS_ORDERED);
            }

            // 删除已有预约重新执行添加预约操作:
            if (flag) {
                for (Integer setMealId : setMealIds) {
                    order = new Order(member.getId(), orderDate, setMealId);
                    orderMapper.deleteRecordByCondition(order);
                    // 再次添加预约信息,插入的数据:会员id,预约日期,预约类型,预约状态,套餐id
                    order = new Order(member.getId(), orderDate, orderType, Order.ORDERSTATUS_NO, setMealId,
                            addressId, null);
                    orderMapper.add(order);
                }
                return new Result(true, "预约成功");
            }
        }

        if (member == null) {
            String idCard = (String) map.get("idCard");
            member = new Member();
            member.setIdCard(idCard);
            member.setRegTime(new Date());
            member.setPhoneNumber(telephone);
            member.setSex((String) map.get("sex"));
            member.setName((String) map.get("name"));
            member.setBirthday(this.getBirthday(idCard));
            member.setFileNumber(ValidateCodeUtils.generateValidateCode4String(5));
            // 插入操作
            memberMapper.add(member);

            if (!flag) {
                return new Result(false, "新会员注册成功,但客户没有预约体检套餐");
            }

            for (Integer setMealId : setMealIds) {
                // 执行预约操作
                order = new Order(member.getId(), orderDate, orderType,
                        Order.ORDERSTATUS_NO, setMealId, addressId, null);
                orderMapper.add(order);
            }
        }

        // 更新预约设置
        OrderSetting orderSetting = new OrderSetting(dbOrderSetting.getVersion(), orderDate);

        int index = ordersettingMapper.updateByCondition(orderSetting);

        while (index == 0) {
            dbOrderSetting = ordersettingMapper.findByOrderDate(orderDate);
            orderSetting = new OrderSetting(dbOrderSetting.getVersion(), orderDate);
            index = ordersettingMapper.updateByCondition(orderSetting);

            if (index > 0) {
                break;
            }
        }
        return new Result(true, MessageConstant.ORDER_SUCCESS);

    }

    /**
     * 3.后台编辑预约设置
     *
     * @param id
     */
    @Override
    public void updateById(Integer id) {
        orderMapper.updateById(id);
    }

    /**
     * 4.后台取消预约
     *
     * @param id
     */
    @Override
    public void deleteById(Integer id) {
        orderMapper.deleteById(id);
    }

    @Override
    public List<Map<String,Object>> findByMemberId(Integer id) throws Exception {
        List<Map<String,Object>> list = orderMapper.findByMemberId(id);
        for (Map<String, Object> map : list) {
            Date medical = (Date) map.get("medical");//体检日期时间字符串
            String medicalStr = DateUtils.parseDate2String(medical);
            map.put("medical", medicalStr);
        }
        return list;
    }


    /**
     * 截取出生日期
     *
     * @param idCard
     * @return
     * @throws ParseException
     */
    private Date getBirthday(String idCard) throws ParseException {
        String date = null;
        if (idCard != null) {
            date = new String(idCard.toCharArray(), 6, 8);
        }
        return new SimpleDateFormat("yyyyMMdd").parse(date);
    }

    private void addOrderInfo(Order order) {

    }
}
